Polish version - English version - Dokumentacja - Download: tg-0.11.tgz

temgen - dokumentacja u¿ytkownika

1. Wprowadzenie

Temgen jest uniwersalnym generatorem kodu, opartym na
jêzyku szablonów. Szablony temgena s± plikami tekstowymi sk³adaj±cymi siê z linii steruj±cych i linii danych. Dzia³anie temgena polega w zasadzie na przepisywaniu linii danych do plików wyj¶ciowych, zgodnie z kolejno¶ci± okre¶lon± przez linie steruj±ce. Przed zapisaniem symbole zmiennych wystêpuj±cych w liniach danych zastêpowane s± przez ich warto¶ci, a symbole funkcji zastêpowane s± wynikiem ich wywo³ania.

Temgen mo¿e s³u¿yæ do generowania dowolnych tekstów, w których wystêpuj± powtarzalne wzorce. Poniewa¿ ca³a logika generacji zawarta jest w szablonach, temgen mo¿e byæ u¿ywany do generowania kodu w dowolnym jêzyku, np. w C, Perlu, HTML, czy angielskim.

Mechanizm @embed i @emit pozwala na elastyczne tworzenie szablonów generuj±cych synchronicznie fragmenty kodu w wielu plikach i w ró¿nych punktach.

2. Wywo³anie programu

Temgen wywo³uje siê w nastêpuj±cy sposób:
    temgen [opcje] file ...    

Obs³ugiwane s± nastêpuj±ce opcje:

3. Jêzyk szablonów

Podstawy S³owa kluczowe Funkcje wbudowane

Dzia³anie generatora

Przebieg wykonania generacji jest nastêpuj±cy: pliki ¼ród³owe wyszczególnione w linii komend s± parsowane w ca³o¶ci, a nastêpnie s± po kolei interpretowane. Interpretacja odbywa siê linia po linii, przy czym kolejno¶æ ta mo¿e zostaæ zmieniona w wyniku interpretacji linii steruj±cych. Plik ¼ród³owy (szablon) sk³ada siê z dwóch rodzajów linii: linii steruj±cych i linii danych.

Linie steruj±ce

Linie steruj±ce rozpoczynaj± siê od znaku @ i identyfikatora komendy. Komendy wyszczególnione s± w tabelce powy¿ej i omówione ni¿ej. S³u¿± do zmiany przebiegu interpretacji (np. @if, @switch), do deklarowania funkcji ( @function ), wykonywania fragmentów kodu, np. w celu nadania pewnych warto¶ci zmiennym ( @ ), a tak¿e okre¶lenia pliku wyj¶ciowego i punktu, w którym ma byæ umieszczony generowany kod ( @output, @embed, @emit ). Linie steruj±ce mog± byæ kontynuowane w kolejnym wierszu. Linia kontynuowana musi koñczyæ siê znakiem backslashem, a w kolejnym wierszu rozpoczynaæ siê znakiem @.

Kontynuacja linii steruj±cej:
    @if ( $bardzo_dlugie_wyrazenie == \
    @     $dalszy_ciag_dlugiego_wyrazenia )       

Linie danych

Linie danych zawieraj± tekst generowanego kodu. Tekst ten ulega rozwiniêciu polegaj±cemu na zast±pieniu wystêpuj±cych w nim wyra¿eñ odpowiednimi warto¶ciami. Po rozwiniêciu tekst wstawiany jest w punkcie emisji. Punkt ten standardowo znajduje siê na koñcu aktualnego pliku wyj¶ciowego, mo¿e byæ jednak zmieniony przy u¿yciu komend @emit i @embed. Plik wyj¶ciowy mo¿e zostaæ ustalony za pomoc± komendy @output.

Linie danych (szablon i wynik)
    @  $name = "Alaska"      
    $name is the best !    
    Alaska is the best !    

W celu ochrony napisów przed ich interpretacj± jako wyra¿eñ nale¿y u¿ywaæ backslasha, który wymusza dos³owne traktowanie tekstu.

Escaping (szablon i wynik)
    @  $name = "Alaska"      
    (zmienna \$name)     
    (zmienna $name)      

Typy danych i wyra¿eñ

W jêzyku szablonów wystêpuj± trzy typy danych: skalary, tablice i struktury. Skalary mog± byæ liczbami lub napisami, tablice indeksowane s± liczbami ca³kowitymi nieujemnymi.

Skalary, tablice i struktury
    @  $s = "BAR"
    @  $n = 2
    @  $tab[1] = "foo" 
    @  $tab[2] = "bar" 
    @  $str = [ name: "FOO", count: 4 ]
      $s   $tab[ 1 ]    $tab[ $n ]
      $str.name, $str.count
      BAR   foo    bar      
      FOO, 4             

Zarówno tablice, jak struktury mog± byæ rozszerzane dynamicznie. W jêzyku istniej± mechanizmy iteracji:

Tablice i struktury - iterowanie
    @  $tab = ["a","b","c",1000]
    @  $str = [ name: "FOO", count: 4, val: 1.20 ]
    @for ($i=0; $i<$size($tab); $i++)
       item $i: $tab[ $i ]
    @endfor
    STRUCTURE:
    @for ($i in $str)
       $i: $str.$i 
    @endfor    
    item 0: a
    item 1: b
    item 2: c
    item 3: 1000
    STRUCTURE:
    name: FOO 
    count: 4 
    val: 1.200000 

Tablice i struktury mog± byæ dowolnie zagnie¿d¿ane:

Zagnie¿d¿one struktury danych:
   @ $data = [ "scalar", [a:"Alaska", b:"Bar"], \     
   @           [1,2,3,4],                       \     
   @           10 ]

Wyra¿enia

Zarówno w komendach kontrolnych, jak w liniach danych mog± wystêpowaæ wyra¿enia. Do dyspozycji s± wyra¿enia sta³e (liczby i napisy), selektory (udostêpniaj±ce elementy tablic lub struktur), konstruktory (pozwalaj±ce tworzyæ struktury i tablice), wyra¿enia arytmetyczne i wywo³ania funkcji. Wyra¿enie mo¿e byæ ujête w symbole $( ); w liniach danych czasem wrêcz musi, poniewa¿ w liniach danych tylko napisy rozpoczynaj±ce siê od znaku $ interpretowane s± jako wyra¿enia. Operator '+' ma dodatkowe znaczenie: oznacza ³±czenie napisów.

Dostêpne operatory (semantyka jak w jêzyku C):
    -          ==        ++ (postfiksowy i prefiksowy)  
    +          !=        -- (postfiksowy i prefiksowy)   
    *           =        &&
    /           <        ||
    -=          >
    +=         <=
    *=         >=
    /=          !

Przyk³ady wyra¿eñ:
    1    1.01   "foo"   'bar'    
    $x -= 10
    [ 1, 2, "FOO" ]
    [ name: "foo", val: 0 ]
    $fun( 10, $x )
    $var.x
    $var.$field
    $tab[ 10 ]
    $( 'Foo bar bazoola' )
    liczby i napisy
    wyra¿enie arytmetyczne
    konstruktor tablicy
    konstruktor struktury
    wywo³anie funkcji
    selektor (dostêp do pola)
    selektor (dostêp do pola przez nazwê)  
    selektor (dostêp do elementu)  
    wyra¿enie w nawiasach

Interpretacja linii danych polega na zast±pieniu wystêpuj±cych w niej wyra¿eñ przez ich obliczone warto¶ci. Je¿eli wyra¿enie jest wywo³aniem funkcji, warto¶ci± jest dana zwrócona z wewn±trz funkcji za pomoc± instrukcji @return. Interpretacja linii danych zawartych wewn±trz takiej funkcji nie powoduje emitowania tekstu. Odwrotnie jest w przypadku wywo³ania funkcji z linii kontrolnej. Warto¶æ zwracana za pomoc± instrukcji @return jest wtedy ignorowana, a linie danych z wnêtrza funkcji emitowane s± na wyj¶ciu. Brzmi to zawile, ale staje siê jasne po zapoznaniu siê z przyk³adem:

Wywo³anie funkcji:
    @function fun()
        inline text
    @   return "RESULT TEXT"    
    @endfunction
    called from data line: $fun()  
    @ $fun()    
    called from data line: RESULT TEXT   
        inline text

Komendy steruj±ce

@

Interpretacja linii rozpoczynaj±cej siê od znaku @, po którym nastêpuje wyra¿enie polega na obliczeniu tego wyra¿enia. Warto¶æ tego wyra¿enia jest ignorowana - chodzi, podobnie jak w jêzyku C, o skutki uboczne interpretacji.

Komendy - wyra¿enia
    @ $fun()    
    @ $x = 1

@ break

Komenda @break dzia³a podobnie jak instrukcja break w jêzyku C. Przerywa pêtle @for i instrukcjê @switch.

Komenda @break:
    @for ( $i=0; $i<10; $i++ )  
       iteration  $i
    @  break
    @endfor
      
    @switch ( 1 )
    @  case 1:
       branch 1
    @  break   
    @  case 2:
       branch 2
    @endswitch    
   iteration  0     
   branch 1

@ embed
@ emit

Para komend @embed i @emit umo¿liwia zmianê kolejno¶ci generowanych linii. @embed pozwala zdefiniowaæ punkt, w którym emitowany bêdzie tekst, @emit skierowuje strumieñ wyj¶cia do zdefiniowanego gdziekolwiek punktu. Wa¿ne jest to, ¿e punkt ten (definiowany przez @embed) mo¿e byæ zadeklarowany w innym pliku ¼ród³owym, po - lub przed u¿yciem @emit i mo¿e le¿eæ w innym pliku wyj¶ciowym. Komendy te wraz z @pop, @push i @output stanowi± jeden z najsilniejszych mechanizmów temgena.

Argumentem komend @embed i @emit mo¿e byæ dowolne wyra¿enie, nie koniecznie sta³y napis.

@embed 'Nazwa' oznacza: tu emituj tekst po napotkaniu @emit 'Nazwa'.
@emit 'Nazwa' oznacza: emituj tekst w punkcie oznaczonym @embed 'Nazwa'.

Punkty emisji:
    @embed "header"
    @embed "body"
    @embed "footer"   
    @emit  "body"
      BODY TEXT
    @emit  "footer"
      FOOTER TEXT
    @emit  "header"    
      HEADER TEXT
    HEADER TEXT   
    BODY TEXT
    FOOTER TEXT

@ for

Podstawowa forma pêtli @for dzia³a podobnie jak w jêzyku C . Pêtla mo¿e zostaæ przerwana komend± @break. Druga forma umo¿liwia iteracjê pól struktury o nieznanych apriori nazwach.

Pêtle:
    @for ( $i=0; $i<3; $i++ )
       item  $i
    @endfor

    @  $str = [ a: "FOO", b: "BAR" ]    
    @for ( $fld in $str )
       $fld: $str.$fld 
    @endfor    
       item  0     
       item  1
       item  2
       a: FOO 
       b: BAR 

@ function

Komenda @function s³u¿y do definiowania funkcji. W nag³ówku funkcji podaje siê nazwy parametrów. Komenda @return s³u¿y do zwracania rezultatu funkcji. Efekt wywo³ania funkcji zale¿y od tego, czy wywo³ano j± z linii danych, czy z linii kontrolnej. Zosta³o to omówione powy¿ej. Funkcje mog± byæ wywo³ywane w dowolnym pliku ¼ród³owym, przed, lub po deklaracji. Do deklarowania zmiennych lokalnych s³u¿y komenda @local.

Funkcja:
    @function factor( n )
    @  if ( $n == 1 )
    @     return 1
    @  else
    @     return $n * $factor( $n - 1 )   
    @  endif    
    @endfunction
   
    @for ( $i=1; $i<8; $i++ )
       $i ! = $factor($i)
    @endfor
     1 ! = 1
     2 ! = 2
     3 ! = 6
     4 ! = 24
     5 ! = 120
     6 ! = 720
     7 ! = 5040    

@ if

Konstrukcja @if jest klasyczna. Nie wymaga komentarza. Jest zaprezentowana w wielu przyk³adach.

@ local

Instrukcja @local s³u¿y do deklarowania lokalnych zmiennych wewn±trz funkcji.

Zmienna lokalna:
   @function abc(a,b)   
   @local c    
      $a $b $c
   @   $a='anew'
   @   $b='bnew'
   @   $c='cnew'
      $a $b $c
   @endfunction
   
   @ $a='a'
   @ $b='b'
   @ $c='c'

   $a $b $c
   @ $abc( $a, $b )
   $a $b $c
    a b c
        a b 
        anew bnew cnew   
    a b c

@ output

Interpretacja komendy @output powoduje prze³±czenie wyj¶cia do pliku o nazwie podanej jako argument. Razem z komendami @embed, @emit, @pop i @push tworzy zestaw umo¿liwiaj±cy sterowanie wyj¶ciem. Specjalna nazwa pliku "stdout" s³u¿y do przekierowania wyniku na standardowe wyj¶cie programu.

Sterowanie wyj¶ciem:
    @output "foo" 
      FOO
    @output "stdout"  
      STDOUT

@ pop
@ push

Komendy @pop i push s³u¿± do zachowania i odtworzenia punktu emisji. Punkt emisji ustalany jest przez wykonanie komend @output (plik) i @emit (linia). @pop i @push przydatne s± wewn±trz funkcji, pozwalaj±c odtworzyæ stan punktu emisji sprzed jej wywo³ania.

@Push i @pop:
    @function decl( d )
    @  push
    @  output "example.h"
         $d
    @  pop
    @endfunction    
            
    @output "example.c"
        
    #include "example.h"
        
    @ $decl( "int i;" )
        
    int main()
    {
    @ $decl( "int result;" )   
          return result;    
    }
example.h:

   int i;
   int result;

example.c:

#include "example.h"   
int main()
{
      return result;    
}

@ return

Instrukcja @return umo¿liwia zakoñczenie wykonania funkcji i zwrócenie rezultatu.

@ switch

Komenda @switch ma sk³adniê podobn± do analogicznej instrukcji jêzyka C. Ró¿nica polega na tym, ¿e etykietami mog± byæ dowolne wyra¿enia, co ilustruje poni¿szy przyk³ad. Instrukcja @break ma tu zastosowanie analogiczne jak w jêzyku C.

Komenda @switch:
    @function string( len )
    @  if ( $len == 1 )
    @     return "z"
    @  else
    @     return "z" + $string( $len-1 )   
    @  endif 
    @endfunction    
      
    @switch "zz"
    @  case $string(1) :
          1
    @     break  
    @  case $string(2) :
          2
    @     break  
    @  case $string(3) :
          3
    @     break  
    @endswitch
     2      

@ use

Komenda @use (znana z jêzyka Perl) pozwala za³adowaæ kod szablonu z innego pliku. Nazwa pliku musi byæ podana w postaci sta³ego stringu. Kod za³adowanego szablonu nie jest interpretowany, s± natomiast dostêpne zdefiniowane w nim funkcje. Temgen dba o to, aby modu³y nie by³y ³adowane wielokrotnie.

Komenda @use:
   @use "foo.tg"    
   @  $foo()
   FOO     

$printf()

Funkcja $printf s³u¿y do formatowania wyra¿eñ i dzia³a podobnie do funkcji z rodziny printf (3).

$printf()
    $printf( "%-10s %d 0x%02X", "foo", 10, 10 ) 
 foo        10 0x0A  

$size()

Funkcja $size zwraca rozmiar (liczbê pól) obiektu z³o¿onego.

$size()
    @ $x = 1
    @ $y = [ 1, 2, 3 ]
    @ $z = [ a:"foo", b:10 ]
    
    $size($x)  $size($y)  $size($z)  $size($undef)  
  0  3  2  0   

$strlen()

Funkcja $strlen zwraca d³ugo¶æ napisu.

$strlen()
    @ $x = 1
    @ $y = "Foo Bar"
   
    $strlen($x)  $strlen($y)  $strlen($undef)
    0  7  0   

$substr()

Funkcja $substr zwraca fragment stringu pocz±wszy od zadanego znaku, o podanej d³ugo¶ci (lub do koñca, je¶li podano tylko dwa argumenty).

$substr()
    $substr( "ABCDEFGHIJK", 2, 5 )
    $substr( "ABCDEFGHIJK", 2 )
    $substr( "ABCDEFGHIJK", 2, 50 )
  CDEFG
  CDEFGHIJK   
  CDEFGHIJK

$system()

Funkcja $system wykonuje polecenie systemowe, czyta jego wyj¶cie standardowe i zwraca jego zawarto¶æ jako rezultat.

$system()
    $system("ps")   
      PID TTY          TIME CMD
      348 pts/0    00:00:00 bash   
      713 pts/0    00:00:00 tg
      714 pts/0    00:00:00 ps

$tplfile()
$tplline()

Funkcje $tplfile i $tplline zwracaj± odpowiednio nawê pliku i numer linii szablonu, w miejscu, z którego zosta³y wywo³ane.

$tplfile(), $tplline()
    \#line  $tplline()  \"$tplfile()\"     
#line  2  "sample.tg"      

4. Przyk³ady

W katalogu sample/ znajduje siê kilka przyk³adowych szablonów.
  1. sample/class/ - przyk³ad u¿ycia temgena do generowania kodu w C++
  2. sample/docex/ - przyk³ady z dokumentacji (któr± czytasz)
  3. sample/getopt/ - klasyczny przyk³ad, dotycz±cy obs³ugi opcji programu

5. Kontakt z autorem, licencja

Autorem temgena jest Marek £êtowski (mletowski@firma.interia.pl). Wszelkie uwagi i rady s± mile widziane. Program udostêpniony jest publicznie wraz z pe³nym kodem ¼ród³owym, w oparciu o licencjê GNU.


Polish version - English version - Dokumentacja - Download: tg-0.11.tgz